package com.factory;

import com.database.common.Service;
import org.reflections.Reflections;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA by ChouFy on 2020-02-28.
 *
 * @author zhoufy
 */
public class BeanAnnotationFactory {


    private static BeanAnnotationFactory beanFactory = new BeanAnnotationFactory();

    public static BeanAnnotationFactory getInstance() {
        return beanFactory;
    }

    /**
     * 通过自定义注解加载类
     */

    private static Map<String, Object> map = new HashMap<>();

    static {
        try {
            Reflections reflections = new Reflections("com");

            //  指定指定注解生命的class set
            Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(Service.class);

            for (Class<?> aClass : classSet) {
                Service service = aClass.getAnnotation(Service.class);
                //  获取service 注解中给的名称
                String name = service.name();
                // 实例化类
                Object bean = aClass.newInstance();

                if( name.trim().length() == 0){
                    //  获取实现的接口集合
                    Class<?>[] interfaces = aClass.getInterfaces();
                    if (interfaces.length > 0) {
                        for (Class interfaceClass : interfaces) {
                            String beanId = getBeanId(interfaceClass.getName());
                            map.put(beanId, bean);
                        }
                    } else {
                        //  如果没有实现接口，将自身类的类名作为beanid 存入到map中
                        String beanId = getBeanId(aClass.getName());
                        map.put(beanId, bean);
                    }
                } else {
                    map.put(name, bean);
                }
            }

            //  设置类的属性
            for (Class<?> aClass : classSet) {

                Service service = aClass.getAnnotation(Service.class);
                //  获取service 注解中给的名称
                String name = service.name();

                Field[] declaredFields = aClass.getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    declaredField.setAccessible(true);
                    Object obj = map.get(declaredField.getName());
                    //  如果map中没有获取到对应的bean 将不执行操作
                    if (obj != null) {
                        Class<?>[] interfaces = aClass.getInterfaces();
                        if (interfaces.length > 0) {
                            for (Class interfaceClass : interfaces) {
                                name = name.trim().length() == 0 ? getBeanId(interfaceClass.getName()) : name;
                                Object bean = map.get(name);
                                declaredField.set(bean, obj);
                            }
                        } else {
                            name = name.trim().length() == 0 ? getBeanId(aClass.getName()) : name;

                            Object bean = map.get(name);
                            declaredField.set(bean, obj);
                        }
                    }
                }
                // 简单递归一下 获取一下上级父类的属性
                Field[] superClassField = aClass.getSuperclass().getDeclaredFields();
                for (Field declaredField : superClassField) {
                    declaredField.setAccessible(true);
                    Object obj = map.get(declaredField.getName());
                    if (obj != null) {
                        Class<?>[] interfaces = aClass.getInterfaces();
                        if (interfaces.length > 0) {
                            for (Class interfaceClass : interfaces) {
                                String beanId = getBeanId(interfaceClass.getName());
                                Object bean = map.get(beanId);
                                declaredField.set(bean, obj);
                            }
                        } else {
                            String beanId = getBeanId(aClass.getName());
                            Object bean = map.get(beanId);
                            declaredField.set(bean, obj);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     *    设置beanid   类名 首字母小写作为 beanid
     * @param interfaceName 接口或类本身的全限定名
     * @return
     */
    public static String getBeanId(String interfaceName) {
        String beanId = interfaceName.substring(interfaceName.lastIndexOf(".") + 1);
        return beanId.substring(0, 1).toLowerCase() + beanId.substring(1);
    }

    public Object getObject(String id) {
        return map.get(id);
    }
}
